﻿using System.Collections.Generic;
using System.Linq;
using com.cruxomatic.DTOs;
using com.cruxomatic.BusinessObjects;
using com.cruxomatic.BusinessObjects.DatabaseQueries;
using com.cruxomatic.exceptions;

namespace com.cruxomatic.BusinessFacades
{
    public class RoleFacade
    {

        public List<RoleInformation> GetAllRoles(int companyid)
        {
            Queries queries = new Queries();
            IEnumerable<RoleInformation> roles = from rolelist in queries.GetRoles(companyid)
                                                 select ClassConverter.CopyRoleToRoleInformation(rolelist);
            return roles.ToList();
        }

        public List<RoleInformation> GetAllRoles()
        {
            Queries queries = new Queries();
            IEnumerable<RoleInformation> roles = from rolelist in queries.GetAllRoles()
                                                 select ClassConverter.CopyRoleToRoleInformation(rolelist);
            return roles.ToList();

        }

        public List<RoleInformation> GetNonSuperAdminisativeRoles(int companyid)
        {
            Queries queries = new Queries();
            IEnumerable<RoleInformation> roles = from rolelist in queries.GetRolesNotHavingPrivilage(companyid, PermissionLiterals.SuperAdministrative)
                                                 select ClassConverter.CopyRoleToRoleInformation(rolelist);
            return roles.ToList();
        }

        public List<RoleInformation> GetRolesForUser(int userid)
        {
            Queries queries = new Queries();
            IEnumerable<RoleInformation> roles = from rolelist in queries.GetRolesForUser(userid)
                                                 select ClassConverter.CopyRoleToRoleInformation(rolelist);
            return roles.ToList();
        }

        public List<RoleInformation> GetAdministrativeRoles()
        {
            return GetRolesByPrivilage(PermissionLiterals.LocalAdministrative);
        }

        public List<RoleInformation> GetSuperAdministativeRoles()
        {
            return GetRolesByPrivilage(PermissionLiterals.SuperAdministrative);
        }

        public List<RoleInformation> GetRolesByPrivilage(string PrivilageName)
        {
            Queries queries = new Queries();
            IEnumerable<RoleInformation> roleInformations = from rolelist in queries.GetRoles(PrivilageName)
                                                            select ClassConverter.CopyRoleToRoleInformation(rolelist);
            return roleInformations.ToList();
        }

        public List<string> GetRoleNamesByPrivilage(string PrivilageName)
        {
            return GetRolesByPrivilage(PrivilageName).Select(p => p.RoleName).ToList();
        }
        //---------------------------Role Related----------------------------

        public List<RoleInformation> GetRoles()
        {
            Queries query = new Queries();
            IEnumerable<RoleInformation> roles =
                from roleList in query.GetAllRoles()
                select ClassConverter.CopyRoleToRoleInformation(roleList);
            return roles.ToList();
        }

        public RoleInformation GetRole(int RoleID)
        {
            if (RoleID == 0) return new RoleInformation();
            Queries rolenQuery = new Queries();
            Role role = rolenQuery.GetRole(RoleID);
            return ClassConverter.CopyRoleToRoleInformation(role);
        }

        public void SaveRole(RoleInformation role, List<int> privilageIDList, List<int> companyTypeIDList)
        {
            CheckValidity(role);
            Queries query = new Queries();
            Role dbRole = new Role();
            if (role.RoleID != 0)
                dbRole = query.GetRole(role.RoleID);

            dbRole = ClassConverter.CopyRoleInformationToRole(role, dbRole);
            if (role.RoleID == 0)
                query.InsertRole(dbRole, false);
            
            SavePrivilagesForRole(dbRole, privilageIDList, query);
            SaveCompanyTypesForRole(dbRole, companyTypeIDList, query);
            query.SubmitChanges();

        }

        private void SaveCompanyTypesForRole(Role dbRole, List<int> companyTypeIDList, Queries query)
        {
            IEnumerable<RolesByCompanyType> dbRolesByCompanyType = dbRole.RolesByCompanyTypes;
            
            //Remove Privilage Assignment
            foreach (RolesByCompanyType rolesByCompanyType in dbRolesByCompanyType)
            {
                if (!companyTypeIDList.Contains(rolesByCompanyType.CompanyTypeID))
                    query.RemoveCompanyTypesFromRole(rolesByCompanyType ,false);
            }

            // Add Role Assignment
            foreach (int companyTypeID in companyTypeIDList)
            {
                int id = companyTypeID;
                if (dbRolesByCompanyType.Where(p => p.CompanyTypeID == id).Count() == 0)
                {
                    RolesByCompanyType rolesByCompanyType = new RolesByCompanyType();
                    rolesByCompanyType.CompanyTypeID = companyTypeID;
                    rolesByCompanyType.RoleID = dbRole.RoleID;
                    dbRole.RolesByCompanyTypes.Add(rolesByCompanyType);
                }
            }   
        }

        private void SavePrivilagesForRole(Role dbRole, List<int> privilageIDList, Queries query)
        {
           IEnumerable<RolePrivilage> dbRolePrivilage = dbRole.RolePrivilages;
            
            //Remove Privilage Assignment
            foreach (RolePrivilage rolePrivilage in dbRolePrivilage)
            {
                if (!privilageIDList.Contains(rolePrivilage.PrivilageID))
                   query.RemovePrivilagesFromRole(rolePrivilage, false);
            }

            // Add Role Assignment
            foreach (int privilageID in privilageIDList)
            {
                int id = privilageID;
                if (dbRolePrivilage.Where(p => p.PrivilageID == id).Count() == 0)
                {
                    RolePrivilage rolePrivilage = new RolePrivilage();
                    rolePrivilage.PrivilageID = privilageID;
                    rolePrivilage.RoleID = dbRole.RoleID;
                    dbRole.RolePrivilages.Add(rolePrivilage);
                }
            }
        }

    
        public void DeleteRole(int RoleID)
        {
            Queries query = new Queries();
            Role role = query.GetRole(RoleID);
            query.DeleteRole(role);
        }

        private void CheckValidity(RoleInformation role)
        {

            if (DoesRoleExist(role))
                throw CruxExceptionManager.CreateNewDatabaseException("910");
        }

        public bool DoesRoleExist(RoleInformation role)
        {
            Queries query = new Queries();
            Role dbRole = query.GetRole(role.RoleName);
            if (dbRole != null && dbRole.RoleID != role.RoleID)
                return true;
            return false;
        }

        public List<RoleInformation> GetRolesByCompanyType(string CompanyType)
        {
            Queries query = new Queries();
            IEnumerable<RoleInformation> roles = from allroles in query.GetRolesByCompanyType(CompanyType)
                                                 select ClassConverter.CopyRoleToRoleInformation(allroles);
            return roles.ToList();
        }

        public List<RoleInformation> GetGlobalAdministativeRoles()
        {
            return GetRolesByPrivilage(PermissionLiterals.GlobalAdministrative);
        }
    }
}
